package com.sinopec.basemodule.base.basekt

import com.sinopec.basemodule.base.BaseActivity
import com.sinopec.basemodule.base.BaseFragment
import com.sinopec.basemodule.http.ExceptionEngine
import com.sinopec.basemodule.http.api.HttpResult
import com.sinopec.basemodule.http.func.HttpResponseFunc
import com.sinopec.basemodule.http.func.ServerResponseFunc
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.lang.Exception


/**
 *
 */
fun <T> BaseActivity<*>.request(
    request: Observable<HttpResult<T?>>,
    onerror: ((ExceptionEngine.ResponseThrowable?) -> Unit)? = null,
    onsuccess: (t: T?) -> Unit,
) {
    disposables.add(
        request
            .transHttpResultPackage()
            .subscribe({
                onsuccess(it)
            }, {
                onerror?.invoke(it as? ExceptionEngine.ResponseThrowable)
            })
    )
}

/**
 *
 */
fun <T> BaseFragment<*>.request(
    request: Observable<HttpResult<T?>>,
    onerror: ((ExceptionEngine.ResponseThrowable?) -> Unit)? = null,
    onsuccess: (t: T?) -> Unit,
) {
    addDisposable(
        request
            .transHttpResultPackage()
            .subscribe({
                onsuccess(it)
            }, {
                onerror?.invoke(it as? ExceptionEngine.ResponseThrowable)
            })
    )
}

/**
 * 转换 拆包 ，线程，
 */
fun <T> Observable<HttpResult<T?>>.transHttpResultPackage(): Observable<T?> {
    return this
        .map(ServerResponseFunc())
        .onErrorResumeNext(HttpResponseFunc())
        .subscribeOn(Schedulers.io())
        .unsubscribeOn(Schedulers.io())
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread())
}

/**
 * 异常捕获
 */
suspend fun <T> around(
    resultInvoke: suspend () -> T,
): Result<T> {
    return try {
        Result.success(resultInvoke())
    } catch (e: Exception) {
        Result.failure(ExceptionEngine.handleException(e))
    }
}

/**
 * 方便取数据
 */
fun <T> Result<HttpResult<T?>>.dataOrNull(): T? {
    return this.getOrNull()?.data
}